﻿using System;
using System.Text;
using System.Linq;
using System.Windows;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;

using Cratos.Tools.General;

namespace Cratos.Generator
{
	/// <summary>
	/// MVP Presenter class
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class MVPPresenter<T> : IMVPPresenter<T>
	{
		#region Class Constant declarations
		#endregion

		#region Class Event declarations
		/// <summary>
		/// Progress Start event
		/// </summary>
		public event MVPProgressEvent ProgressStart;

		/// <summary>
		/// Progress End event
		/// </summary>
		public event MVPProgressEvent ProgressEnd;

		/// <summary>
		/// Progress Update event
		/// </summary>
		public event MVPProgressUpdateEvent ProgressUpdate;

		/// <summary>
		/// Property Changed event
		/// </summary>
		[field: NonSerialized]
		public event PropertyChangedEventHandler PropertyChanged;
		#endregion

		#region Class Variable declarations
		private	T												m_View;
		private string									m_Header					= "<< Unknown >>";

		private long										m_TransactionTime = 0;
		private Collection<CratosError>	m_Errors					= new Collection<CratosError>();
		#endregion

		#region Class Constructors & Destructors
		/// <summary>
		/// Class Constructor
		/// </summary>
		public MVPPresenter(T appView)
		{
			// Save the relevant values
			this.m_View = appView;
		}
		
		/// <summary>
		/// Class Constructor
		/// </summary>
		public MVPPresenter(T appView, string viewHeader)
		{
			// Save the relevant values
			this.m_View		= appView;
			this.m_Header	= viewHeader;
		}
		#endregion

		#region Class Properties
		/// <summary>
		/// View
		/// </summary>
		public T View
		{
			get { return (this.m_View); }
		}

		/// <summary>
		/// View Header
		/// </summary>
		public string Header
		{
			get { return (this.m_Header); }
		}

		/// <summary>
		/// Errors
		/// </summary>
		public Collection<CratosError> Errors
		{
			get { return (this.m_Errors); }
		}

		/// <summary>
		/// Error Message
		/// </summary>
		public string ErrorMessage
		{
			get
			{
				// Declare the required variables
				StringBuilder errorMsg;

				// Create the relevant error message
				errorMsg = new StringBuilder();
				foreach (CratosError currentMsg in this.m_Errors)
				{
					if (currentMsg.RuntimeException == null)
					{
						errorMsg.AppendFormat("[{0}] [{1}-[{2}] {3}", currentMsg.Severity,
																																currentMsg.Date.ToString("dd/MM/yyyy HH:mm:ss"),
																																currentMsg.Source,
																																currentMsg.Message);
					}
					else
					{
						errorMsg.AppendFormat("[{0}] [{1}-[{2}] {3} - {4}", currentMsg.Severity,
																																currentMsg.Date.ToString("dd/MM/yyyy HH:mm:ss"),
																																currentMsg.Source,
																																currentMsg.Message,
																																currentMsg.RuntimeException.ToString());
					}
				}

				// Return to calling method
				return (errorMsg.ToString());
			}
		}

		/// <summary>
		/// Transaction Time
		/// </summary>
		public long TransactionTime
		{
			get { return (this.m_TransactionTime); }
			set { this.m_TransactionTime = value; this.OnNotifyPropertyChanged("TransactionTime"); }
		}
		#endregion

		#region Class Methods
		/// <summary>
		/// Display error
		/// </summary>
		/// <param name="viewName">View Name</param>
		public void DisplayError(string viewName)
		{
			// Declare the required variables
			StringBuilder errorMessage;

			// Create and setup the Error Message
			errorMessage = new StringBuilder();
			errorMessage.AppendLine("Runtime Error occurred");
			errorMessage.AppendLine(this.ErrorMessage);

			// Display the error message
			MessageBox.Show(errorMessage.ToString(), viewName, MessageBoxButton.OK, MessageBoxImage.Error);

			// Return to calling method
			return;
		}

		/// <summary>
		/// Notify Property Changed method
		/// </summary>
		/// <param name="changeInfo">Change information</param>
		public virtual void OnNotifyPropertyChanged(string changeInfo)
		{
			// Declare the required variables

			// Make sure we have somebody listening
			if (this.PropertyChanged != null)
			{
				// Raise the Property Changed event
				this.PropertyChanged(this, new PropertyChangedEventArgs(changeInfo));
			}

			// Return to calling method
			return;
		}

		/// <summary>
		/// Progress Start Method
		/// </summary>
		public void OnProgressStart()
		{
			// Declare the required variables

			// Raise the relevant event
			if (this.ProgressStart != null) { this.ProgressStart(); }

			// return to calling method
			return;
		}

		/// <summary>
		/// Progress End method
		/// </summary>
		public void OnProgressEnd()
		{
			// Declare the required variables

			// Raise the relevant event
			if (this.ProgressEnd != null) { this.ProgressEnd(); }

			// return to calling method
			return;
		}

		/// <summary>
		/// Progress Update method
		/// </summary>
		/// <param name="progressMessage"></param>
		public void OnProgressUpdate(string progressMessage)
		{
			// Declare the required variables

			// Raise the relevant event
			if (this.ProgressUpdate != null) { this.ProgressUpdate(progressMessage); }

			// return to calling method
			return;
		}
		#endregion

		#region Class Support Methods
		#endregion
	}
}
